package observer

import "fmt"

type Subject interface {
	Register(Observer)
	Deregister(Observer)
	Notify()
}

type Observer interface {
	Update(Subject)
}


type ConcreteSubject struct {
	state     string
	observers []Observer
}

func (s *ConcreteSubject) Register(observer Observer) {
	s.observers = append(s.observers, observer)
}

func (s *ConcreteSubject) Deregister(observer Observer) {
	for i, o := range s.observers {
		if o == observer {
			copy(s.observers[i:], s.observers[i+1:])
			s.observers=  s.observers[:len(s.observers)-1]
			break
		}
	}
}

func (s *ConcreteSubject) Notify() {
	for _, observer := range s.observers {
		observer.Update(s)
	}
}

func (s *ConcreteSubject) SetState(state string) {
	s.state = state
	s.Notify()
}

func (s *ConcreteSubject) GetState() string {
	return s.state
}

type ConcreteObserverA struct {
	Name string
}

func (c *ConcreteObserverA) Update(subject Subject) {
	fmt.Printf("ObserverA: %s has received state: %s\n", c.Name, subject.(*ConcreteSubject).GetState())
}

type ConcreteObserverB struct {
	Name string
}

func (c *ConcreteObserverB) Update(subject Subject) {
	fmt.Printf("ObserverB: %s has received state: %s\n", c.Name, subject.(*ConcreteSubject).GetState())
}


